import { Repository, UpdateResult } from "typeorm";
import { LogServerHelper } from "../../log_server/LogServerHelper";
import { DbConfig } from "../../src/config/DbConfig";
import { GameConfig } from "../../src/config/GameConfig";
import { DaoBase } from "../../src/engine/dao/DaoBase";
import { Base64Helper } from "../../src/engine/utils/Base64Helper";
// import { Base64Helper } from "../../src/engine/utils/Base64Helper";
import DateUtil from "../../src/engine/utils/DateUtil";
import { Logger } from "../../src/engine/utils/Logger";
import { MysqlClient } from "../../src/engine/utils/MySqlClient";
import { MysqlManager } from "../../src/engine/utils/MysqlManager";
import { ServerManager } from "../../src/server/ServerManager";
import { UserEntity } from "../entity/UserEntity";
import { AccountDao } from "./AccountDao";
import { UserResourceDao } from "./UserResourceDao";

export class UserDao extends DaoBase {

    public static Tb_Name: string = "t_users";

    public static async getRepository() {
        let repository: Repository<UserEntity> = await this.getRepositoryBase(UserEntity, this.getGameDbName())
        return repository;
    }

    public static async getUserNum() {
        let repository: Repository<UserEntity> = await this.getRepository()
        let count: number = await repository.count()
        return count
    }

    public static async is_user_exist_by_userid(userid: number): Promise<any> {
        let repository: Repository<UserEntity> = await this.getRepository()
        let result: UserEntity = await repository.findOneBy({
            userid: userid
        })
        if (result) {
            return true
        }
        else {
            return false
        }
    }

    public static async update_user(entity: UserEntity) {
        let repository: Repository<UserEntity> = await this.getRepository()
        let result: UserEntity
        if (!repository.hasId(entity)) {
            result = await repository.save(entity)
        } else {
            let updateResult:UpdateResult = await repository.update({ userid: entity.userid }, entity)
            // { generatedMaps: [], raw: [], affected: 1 }
            if (updateResult && updateResult.affected > 0) {
                result = entity
            }
        }
        return result
    }



    public static async get_user_data_by_userid(userid: number): Promise<UserEntity> {
        let repository: Repository<UserEntity> = await this.getRepository()
        let result: UserEntity = await repository.findOneBy({
            userid: userid
        })
        return result
    }

    public static async get_user_data_by_account(account: string): Promise<UserEntity> {
        let repository: Repository<UserEntity> = await this.getRepository()
        let result: UserEntity = await repository.findOneBy({
            account: account
        })
        Logger.log("get_user_data_by_account", result)
        return result
    }


    public static async get_userlistinfo(useridList: Array<number>): Promise<Array<UserEntity>> {
        if (useridList.length > 0) {
            let repository: Repository<UserEntity> = await this.getRepository()
            let sql = "select * from  t_users where `userid`=" + useridList[0];
            for (let i = 1; i < useridList.length; i++) {
                sql += " or `userid`=" + useridList[i];
            }
            let results = await repository.query(sql)
            if (results && results.length) {
                return results
            }
        }
        return []
    }

    public static async setRoom_id(userid: number, room_id: number) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let sql = "update " + this.getGameDbName() + "." + this.Tb_Name + " set `room_id`=?  where `userid`=?";
        let sqlParams = [room_id, userid];
        let results = await client.queryPromise(sql, sqlParams);
        if (results && results["affectedRows"] > 0) {
            return true
        }
        else {
            return false
        }
    }

    public static async getGems(userid: number) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let sql: string = "select gems from t_users WHERE userid = ?";
        let sqlParams = [userid];
        let results = await client.queryPromise(sql, sqlParams);
        Logger.log("getGems==", results)
        if (results && results.length) {
            return results[0]["gems"]
        }
    }

    public static async decGems(userid: number, decNum: number) {
        if (decNum > 0) {
            let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
            let gems: number = await this.getGems(userid)
            gems -= decNum
            if (gems < 0) {
                gems = 0
            }
            let sql: string = 'UPDATE t_users SET gems =  ?' + ' WHERE userid = ?';
            let sqlParams = [gems, userid];
            let results = await client.queryPromise(sql, sqlParams);
            if (results && results["affectedRows"] > 0) {
                // LogServerHelper.log_add_user_spend_daily(userid, "gems", decNum)
                return gems
            }
            else {
                return gems
            }
        }
    }

    public static async updateGems(userid: number, gems: number) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let sql: string = 'UPDATE t_users SET gems =  ?' + ' WHERE userid = ?';
        let sqlParams = [gems, userid];
        let results = await client.queryPromise(sql, sqlParams);
        if (results && results["affectedRows"] > 0) {
            return gems
        }
        else {
            return gems
        }
    }

    public static async addGems(userid: number, addNum: number) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let gems: number = await this.getGems(userid)
        gems += addNum
        if (gems < 0) {
            gems = 0
        }
        let sql: string = 'UPDATE t_users SET gems =  ?' + ' WHERE userid = ?';
        let sqlParams = [gems, userid];
        let results = await client.queryPromise(sql, sqlParams);
        if (results && results["affectedRows"] > 0) {
            return gems
        }
        else {
            return gems
        }
    }

    public static async addCoins(userid: number, addNum: number) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let coins: number = await this.getCoins(userid)
        coins += addNum
        if (coins < 0) {
            coins = 0
        }
        let sql: string = 'UPDATE t_users SET coins =  ?' + ' WHERE userid = ?';
        let sqlParams = [coins, userid];
        let results = await client.queryPromise(sql, sqlParams);
        if (results && results["affectedRows"] > 0) {
            return coins
        }
        else {
            return coins
        }
    }

    public static async decCoins(userid: number, decNum: number) {
        if (decNum > 0) {
            let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
            let coins: number = await this.getCoins(userid)
            coins -= decNum;
            if (coins < 0) {
                coins = 0
            }
            let sql: string = 'UPDATE t_users SET coins =  ?' + ' WHERE userid = ?';
            let sqlParams = [coins, userid];
            let results = await client.queryPromise(sql, sqlParams);
            if (results && results["affectedRows"] > 0) {
                LogServerHelper.log_add_user_spend_daily(userid, "coins", decNum)
                return coins
            }
            else {
                return coins
            }
        }
    }

    public static async addMeili(userid: number, addNum: number) {
        // if (addNum > 0) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let meilis: number = await this.getMeili(userid)
        meilis += addNum
        if (meilis < 0) {
            meilis = 0
        }
        let sql: string = 'UPDATE t_users SET meilis = ?' + ' WHERE userid = ?';
        let sqlParams = [meilis, userid];
        let results = await client.queryPromise(sql, sqlParams);
        if (results && results["affectedRows"] > 0) {
            return meilis
        }
        else {
            return meilis
        }
        // }
    }

    public static async decMeili(userid: number, decNum: number) {
        if (decNum > 0) {
            let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
            let meilis: number = await this.getMeili(userid)
            meilis -= decNum
            if (meilis < 0) {
                meilis = 0
            }
            let sql: string = 'UPDATE t_users SET meilis =  ?' + ' WHERE userid = ?';
            let sqlParams = [meilis, userid];
            let results = await client.queryPromise(sql, sqlParams);
            if (results && results["affectedRows"] > 0) {
                return meilis
            }
            else {
                return meilis
            }
        }
    }

    public static async getMeili(userid: number) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let sql: string = "select meilis from t_users WHERE userid = ?";
        let sqlParams = [userid];
        let results = await client.queryPromise(sql, sqlParams);
        Logger.log("getMeili==", results)
        if (results && results.length) {
            return results[0]["meilis"]
        }
    }

    public static async getCoins(userid: number) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let sql: string = "select coins from t_users WHERE userid = ?";
        let sqlParams = [userid];
        let results = await client.queryPromise(sql, sqlParams);
        Logger.log("getCoins==", results)
        if (results && results.length) {
            return results[0]["coins"]
        }
    }

    public static async decIncome(userid: number, decNum: number) {
        if (decNum > 0) {
            let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
            let sql: string = 'UPDATE t_users SET income = income - ?' + ' WHERE userid = ?';
            let sqlParams = [decNum, userid];
            let results = await client.queryPromise(sql, sqlParams);
            if (results && results["affectedRows"] > 0) {
                return true
            }
            else {
                return false
            }
        }
    }

    public static async getIncome(userid: number) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let sql: string = "select income from t_users WHERE userid = ?";
        let sqlParams = [userid];
        let results = await client.queryPromise(sql, sqlParams);
        if (results && results.length) {
            return results[0]["income"]
        }
    }

    public static async add_income(userid: number, addNum: number) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let income: number = await this.getIncome(userid)
        income += addNum;
        if (income < 0) {
            income = 0
        }
        let sql: string = 'UPDATE t_users SET income = ?' + ' WHERE userid = ?';
        let sqlParams = [income, userid];
        let results = await client.queryPromise(sql, sqlParams);
        if (results && results["affectedRows"] > 0) {
            return income
        }
        else {
            return income
        }
    }

    public static async update_income(userid: number, income: number) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let sql: string = 'UPDATE t_users SET income =  ? ' + ' WHERE userid = ?';
        let sqlParams = [income, userid];
        let results = await client.queryPromise(sql, sqlParams);
        if (results && results["affectedRows"] > 0) {
            return true
        }
        else {
            return false
        }
    }

    public static async update_income_coins(userid: number, income: number, coins: number) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let sql: string = 'UPDATE t_users SET income =  ? , coins=? ' + ' WHERE userid = ?';
        let sqlParams = [income, coins, userid];
        let results = await client.queryPromise(sql, sqlParams);
        Logger.log("update_income_coins==", sql, sqlParams)
        Logger.log("update_income_coins==2", results)
        if (results && results["affectedRows"] > 0) {
            return true
        }
        else {
            return false
        }
    }

    public static async update_meili_coins(userid: number, meilis: number, coins: number) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let sql: string = 'UPDATE t_users SET meilis =  ? , coins=? ' + ' WHERE userid = ?';
        let sqlParams = [meilis, coins, userid];
        let results = await client.queryPromise(sql, sqlParams);
        Logger.log("update_meili_coins==", sql, sqlParams)
        Logger.log("update_meili_coins==2", results)
        if (results && results["affectedRows"] > 0) {
            return true
        }
        else {
            return false
        }
    }


    public static async saveHeadImg(imgUrl: string, userid: number) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let sql: string = "UPDATE t_users SET headimg = ? WHERE userid = ?";
        let sqlParams = [imgUrl, userid];
        let results = await client.queryPromise(sql, sqlParams);
        Logger.log("saveHeadImg====", sql, sqlParams, results)
        if (results && results["affectedRows"] > 0) {
            return true
        }
        else {
            return false
        }
    }


    public static async setState(userid: number, state: number) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let sql: string = "UPDATE t_users SET state = ? WHERE userid = ?";
        let sqlParams = [state, userid];
        let results = await client.queryPromise(sql, sqlParams);
        if (results && results["affectedRows"] > 0) {
            return true
        }
        else {
            return false
        }
    }

    public static async cancelVip(userid: number) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let sql: string = "UPDATE t_users SET lv =0 WHERE userid = ?";
        let sqlParams = [userid];
        let results = await client.queryPromise(sql, sqlParams);
        if (results && results["affectedRows"] > 0) {
            return true
        }
        else {
            return false
        }
    }


    public static async get_main_statistics_info() {
        let resultObj: object = {
            "accountNum": await AccountDao.getAccountNum(),
            "userNum": await UserDao.getUserNum(),
        }
        return resultObj
    }


    public static async get_user_list(pagenum: number, pagesize: number) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let start: number = (pagenum - 1) * pagesize
        let sql: string = `select * from t_users  limit ?,?`
        let sqlParams = [start, pagesize];
        let results = await client.queryPromise(sql, sqlParams);
        return results
    }


    public static async get_user_normal_daili_list(pagenum: number, pagesize: number) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let start: number = (pagenum - 1) * pagesize
        let sql: string = `select * from t_users  where lv > 0 limit ?,?`
        let sqlParams = [start, pagesize];
        let results = await client.queryPromise(sql, sqlParams);
        return results
    }

    public static async get_normal_daili_xiaji_num(invite: number) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let sql = `select count(userid) as count from t_users where invite = ?`
        let sqlParams = [invite];
        let results = await client.queryPromise(sql, sqlParams);
        let count = (results && results.length) ? results[0].count : 0
        return count
    }

    public static async get_user_normal_daili_count() {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let sql: string = `select count(userid) as count from t_users  where lv > 0`
        let results = await client.queryPromise(sql);
        let count = (results && results.length) ? results[0].count : 0
        return count
    }

    public static async get_user_qudao_daili_list(pagenum: number, pagesize: number) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let start: number = (pagenum - 1) * pagesize
        let sql: string = `select * from t_users  where qudaodaili > 0 limit ?,?`
        let sqlParams = [start, pagesize];
        let results = await client.queryPromise(sql, sqlParams);
        return results
    }

    public static async get_user_qudao_daili_count() {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let sql: string = `select count(userid) as count from t_users  where qudaodaili > 0`
        let results = await client.queryPromise(sql);
        let count = (results && results.length) ? results[0].count : 0
        return count
    }

    public static async set_lv(userid: number, lv: number) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let sql: string = "UPDATE t_users SET lv = ? WHERE userid = ?";
        let sqlParams = [lv, userid];
        let results = await client.queryPromise(sql, sqlParams);
        if (results && results["affectedRows"] > 0) {
            return true
        }
        else {
            return false
        }
    }

    public static async clearInvite(invite: number) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let sql: string = "UPDATE t_users SET invite = ? WHERE invite = ?";
        let sqlParams = [null, invite];
        let results = await client.queryPromise(sql, sqlParams);
        if (results && results["affectedRows"] > 0) {
            return true
        }
        else {
            return false
        }
    }

    public static async get_lv(userid: number) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let sql: string = "select lv from t_users WHERE userid = ?";
        let sqlParams = [userid];
        let results = await client.queryPromise(sql, sqlParams);
        Logger.log("get_lv==", results)
        if (results && results.length) {
            return results[0]["lv"]
        }
    }

    public static async set_qudaodaili(userid: number, qudaodaili: number) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let sql: string = "UPDATE t_users SET qudaodaili = ? WHERE userid = ?";
        let sqlParams = [qudaodaili, userid];
        let results = await client.queryPromise(sql, sqlParams);
        if (results && results["affectedRows"] > 0) {
            return true
        }
        else {
            return false
        }
    }

    public static async get_userids_by_invite_and_no_lv(invite: number) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let sql: string = "select userid from t_users WHERE invite = ? and lv != 1";
        let sqlParams = [invite];
        let results = await client.queryPromise(sql, sqlParams);
        Logger.log("get_userids_by_invite_and_no_lv==", results)
        return results
    }

    public static async getJindouTop(topNum: number) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let startIndex: number = 0
        let sql: string = "select *  from t_users   order by coins desc limit ?,?"
        let sqlParams = [startIndex, topNum];
        let rows = await client.queryPromise(sql, sqlParams);
        Logger.log("getTop=", rows)
        if (rows && rows.length) {
            return rows
        }
        return []
    }


}